using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Audio;

namespace Framework
{
    public class AudioManager : MonoSingleton<AudioManager>
    {
        public string DefaultChannelName = "Master";
        public AudioPlayer defaultPlayer;
        public WrappedDict<AudioMixerGroup, AudioPlayer> Channels;
        private Dictionary<string, AudioMixerGroup> cachedGroups = new();
        private Dictionary<string, AudioPlayer> cachedSources = new();
        private Dictionary<AudioPlayer, GameObjectPool<AudioPlayer>> pools = new();
        
        protected override void Awake()
        {
            base.Awake();
            foreach (var (channel, prefab) in Channels)
            {
                cachedGroups.Add(channel.name, channel);
                cachedSources.Add(channel.name, prefab);
            }
        }
        
        public AudioSource PlaySound(AudioClip clip, string channel = null, Transform parent = null)
        {
            if (string.IsNullOrEmpty(channel) || !cachedGroups.ContainsKey(channel))
            {
                channel = DefaultChannelName;
            }
            
            if (cachedGroups.TryGetValue(channel, out var group))
            {
                var prefab = cachedSources[channel] ?? defaultPlayer;
                if (!prefab) return null;
                if (!pools.TryGetValue(prefab, out var pool))
                    pools.Add(prefab, pool = new GameObjectPool<AudioPlayer>(prefab, transform));
                var palyer = pool.Get();
                var source = palyer.AudioSource;
                source.outputAudioMixerGroup = group;
                source.clip = clip;
                source.transform.parent = parent ?? transform;
                source.Play();
                StartCoroutine(RecyclePlayer(pool, palyer, clip.length * 1.05f));
                return source;
            }
            
            return null;
        }

        public IEnumerator RecyclePlayer(GameObjectPool<AudioPlayer> pool, AudioPlayer player, float seconds)
        {
            yield return new WaitForSeconds(seconds);
            pool.Release(player);
        }
    }
}
